package com.evil.kingdom.controller.action;

import cn.hutool.core.lang.UUID;
import com.evil.common.core.entity.R;
import com.evil.common.core.util.StreamUtil;
import com.evil.kingdom.handler.timer.BattlefieldTimerTaskHandler;
import com.evil.kingdom.handler.timer.WarfareTimerTaskHandler;
import com.evil.kingdom.pojo.dto.action.BattlefieldDto;
import com.evil.kingdom.pojo.dto.action.NavigateDto;
import com.evil.kingdom.pojo.dto.person.general.GeneralDto;
import com.evil.kingdom.pojo.entity.action.*;
import com.evil.kingdom.pojo.entity.action.Vector;
import com.evil.kingdom.pojo.entity.person.general.General;
import com.evil.kingdom.pojo.entity.world.city.City;
import com.evil.kingdom.pojo.enums.BattlefieldTypeEnum;
import com.evil.kingdom.service.action.PositionService;
import com.evil.kingdom.service.action.VectorService;
import com.evil.kingdom.service.person.general.GeneralService;
import com.evil.kingdom.service.world.city.CityService;
import com.evil.kingdom.utils.ChineseNameGeneratorUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 导航本
 *
 * @author liyang
 * @date 2024-05-22 17:11
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/vector")
public class VectorController {

    private final CityService cityService;
    private final VectorService vectorService;
    private final PositionService positionService;
    private final GeneralService generalService;
    private final WarfareTimerTaskHandler warfareHandler;
    private final BattlefieldTimerTaskHandler battlefieldTimerTaskHandler;

    /**
     * 初始化导航本
     *
     * @return R
     */
    @RequestMapping("/init")
    public R<String> init(String suffix) {
        vectorService.init(suffix);
        return R.success();
    }

    /**
     * 重新计算导航本
     *
     * @return R
     */
    @RequestMapping("/reCal")
    public R<String> reCal() {
        List<City> cities = cityService.list();
        Map<String, City> cityMap = StreamUtil.toMapK(cities, City::getName);

        List<Vector> vectors = vectorService.list();
        vectors.forEach(v -> {
            City departCity = cityMap.get(v.getDepartName());
            AbstractPosition depart = v.getPositions().getFirst().getDepart();
            depart.setX(departCity.getX());
            depart.setY(departCity.getY());

            City destCity = cityMap.get(v.getDestName());
            AbstractPosition dest = v.getPositions().getLast().getDest();
            dest.setX(destCity.getX());
            dest.setY(destCity.getY());
        });
        vectorService.getRepository().saveAll(vectors);
        return R.success();
    }

    /**
     * 导航
     *
     * @return R
     */
    @PostMapping("/navigate")
    public R<List<String>> navigate(@RequestBody @Validated NavigateDto navigateDto) {
        List<Vector> vectors = vectorService.list();
        List<RoutePosition> routes = new ArrayList<>();
        vectors.forEach(v -> {
            routes.add(new RoutePosition(v, false));
            routes.add(new RoutePosition(v, true));
        });
        List<String> names = positionService.calShortest(routes, navigateDto.getDepartName(), navigateDto.getDestName());
        return R.success(names);
    }

    /**
     * 出征
     *
     * @return R
     */
    @PostMapping("/warfare")
    public R<Warfare> warfare(@RequestBody @Validated NavigateDto navigateDto) {
        List<Vector> vectors = vectorService.list();
        List<RoutePosition> routes = new ArrayList<>();
        vectors.forEach(v -> {
            routes.add(new RoutePosition(v, false));
            routes.add(new RoutePosition(v, true));
        });
        LinkedList<RoutePosition> routePositions = positionService.warfare(routes, navigateDto.getDepartName(), navigateDto.getDestName());

        List<General> generals = generalService.findByNames(navigateDto.getGeneralNames());
        Warfare warfare = new Warfare(navigateDto.getMarshalName(), new HashSet<>(generals), 1d, routePositions);
        warfareHandler.buildWarfareTimerTask(warfare);
        return R.success(warfare);
    }

    /**
     * 战场
     *
     * @return R
     */
    @PostMapping("/battlefield")
    public R<?> battlefield(@RequestBody @Validated BattlefieldDto battlefieldDto) {
        String offensiveName = battlefieldDto.getOffensiveName();
        String defensiveName = battlefieldDto.getDefensiveName();
        GeneralDto offensive = generalService.findDtoByName(offensiveName);
        GeneralDto defensive = generalService.findDtoByName(defensiveName);

        log.info("battlefield|start");
        String toponym = ChineseNameGeneratorUtil.generateRandomChineseName(3);
        BattlefieldSide side = new BattlefieldSide(offensiveName, defensiveName, Set.of(offensive), Set.of(defensive));
        Battlefield battlefield = new Battlefield(UUID.fastUUID().toString(true), side, BattlefieldTypeEnum.WILDERNESS, toponym);
        battlefieldTimerTaskHandler.buildBattlefieldTimerTask(battlefield, sideName -> {
            log.info("battlefield|controller|finished:{}", sideName.printInfo());
        });
        return R.success();
    }

    /**
     * 新增导航本
     *
     * @param vector vector
     * @return R
     */
    @PostMapping("/add")
    public R<Vector> add(@RequestBody @Validated Vector vector) {
        return R.success(vectorService.add(vector));
    }

    /**
     * 新增导航本
     *
     * @param vector vector
     * @return R
     */
    @PostMapping("/update")
    public R<Vector> update(@RequestBody @Validated Vector vector) {
        return R.success(vectorService.update(vector));
    }

    /**
     * 查询导航本
     *
     * @param name name
     * @return R
     */
    @RequestMapping("/find-by-name")
    public R<Vector> findByName(String name) {
        return R.success(vectorService.findByName(name));
    }

    /**
     * 获取导航本列表
     *
     * @return R
     */
    @RequestMapping("/list")
    public R<List<Vector>> list() {
        return R.success(vectorService.list());
    }
}
